#include "app_buffer.h"
#include <stdlib.h>
#include "log/log.h"
#include <string.h>

//创建一个子缓冲区
static subBuffer *sub_buf_init(int tatol_size)
{
    subBuffer *sub_buf = (subBuffer *)malloc(sizeof(subBuffer));
    sub_buf->ptr = malloc(tatol_size);
    sub_buf->tatol_size = tatol_size;
    sub_buf->len = 0;
    return sub_buf;
}

Buffer *app_buffer_init(int tatol_size)
{
    //创建一个缓冲区包含两个子缓冲区
    Buffer *buf = (Buffer *)malloc(sizeof(Buffer));
    buf->sub_buffers[0] = sub_buf_init(tatol_size);
    buf->sub_buffers[1] = sub_buf_init(tatol_size);
    //初始化读写索引 0和1代表示两个子缓冲区
    buf->read_index = 0;
    buf->write_index = 1;
    
    //初始化读写锁 互斥锁为普通类型（默认类型），
    //在未解锁的情况下再次调用 pthread_mutex_lock 会导致线程阻塞。
    pthread_mutex_init(&buf->read_mutex, NULL);
    pthread_mutex_init(&buf->write_mutex, NULL);
    return buf;
}

void app_buffer_free(Buffer *buf)
{
    //由里至外释放资源
    free(buf->sub_buffers[0]->ptr);
    free(buf->sub_buffers[1]->ptr);
    free(buf->sub_buffers[0]);
    free(buf->sub_buffers[1]);
    free(buf);
}

int app_buffer_write(Buffer *buf, char *data, int data_len)
{
    //限制使用一个字节存储数据长度
    if (data_len > 0xff)
    {
        log_error("data_len too large");
        return -1;
    }

    //加写锁
    pthread_mutex_lock(&buf->write_mutex);

    log_debug("准备写入数据：%.*s,数据长度为%d, 加锁", data_len, data, data_len);

    //获取写缓冲区
    subBuffer *write_buf = buf->sub_buffers[buf->write_index];
    //如果写缓冲区剩余空间不足，则返回
    if (data_len + 1 > write_buf->tatol_size - write_buf->len)
    {
        log_error("write_buf is full");
        pthread_mutex_unlock(&buf->write_mutex);//解锁
        return -1;
    }
    
    //写入数据
    write_buf->ptr[write_buf->len] = data_len;//写入数据长度
    memcpy(write_buf->ptr + write_buf->len + 1, data, data_len);//写入数据
    //更新写缓冲区长度
    write_buf->len += data_len + 1;

    //解锁
    pthread_mutex_unlock(&buf->write_mutex);

    log_debug("准备写入数据完成：%.*s,解锁", data_len, data);

    return 0;
}

static void switch_buffer(Buffer *buf)
{
    //log_debug("准备切换缓冲区， 加写锁");
    //当另一个子缓冲区在写入时不能切换
    pthread_mutex_lock(&buf->write_mutex);
    //切换读写缓冲区
    int temp = buf->read_index;
    buf->read_index = buf->write_index;
    buf->write_index = temp;
    //解锁
    pthread_mutex_unlock(&buf->write_mutex);
    //log_debug("切换缓冲区完成， 解写锁");
}

int app_buffer_read(Buffer *buf, char *data_buf, int buf_size)
{
    //log_debug("准备读取数据， 加读锁");
    //加读锁
    pthread_mutex_lock(&buf->read_mutex);
    //获取读缓冲区
    subBuffer *read_buf = buf->sub_buffers[buf->read_index];
    //当读缓冲区为空时，切换缓冲区
    if (read_buf->len == 0)
    {
        switch_buffer(buf);
        //重新获取读缓冲区
        read_buf = buf->sub_buffers[buf->read_index];
        //当另一个读缓冲区为空时，返回-1
        if (read_buf->len == 0)
        {
            log_error("read_buf is empty");
            pthread_mutex_unlock(&buf->read_mutex);//解锁
            return -1;
        }
    }
    
    //先读取数据长度(内存的第一个字节)
    int data_len = read_buf->ptr[0];
    log_debug("data_len=%d", data_len);
    // 如果数据长度大于buf_size，则错误退出
    if (data_len > buf_size)
    {
        log_error("要读取的数据长度大于buf_size");
        // 解锁
        pthread_mutex_unlock(&buf->read_mutex);
        return -1;
    }
    //再读取数据
    memcpy(data_buf, read_buf->ptr + 1, data_len);

    log_debug("读取数据完成：%.*s", data_len, data_buf);

    //将之后的数据移动到子缓冲区开头
    memmove(read_buf->ptr, read_buf->ptr + data_len + 1, read_buf->len - data_len - 1);
    //更新读缓冲区长度
    read_buf->len -= data_len + 1;
    //更新后，如果读缓冲区为空，则切换缓冲区
    if (read_buf->len == 0)
    {
        switch_buffer(buf);
    }
    //解锁
    pthread_mutex_unlock(&buf->read_mutex);
    //log_debug("解读锁");

    return data_len;
}